package com.syher.springboot.kaptcha.starter.core;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;

import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_DATE;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;

public class GoogleKaptcha implements Kaptcha {

    private DefaultKaptcha kaptcha;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpServletResponse response;

    public GoogleKaptcha(DefaultKaptcha kaptcha) {
        this.kaptcha = kaptcha;
    }

    @Override
    public String render() {
        response.setDateHeader(HttpHeaders.EXPIRES, 0L);
        response.setHeader(HttpHeaders.CACHE_CONTROL, "no-store, no-cache, must-revalidate");
        response.addHeader(HttpHeaders.CACHE_CONTROL, "post-check=0, pre-check=0");
        response.setHeader(HttpHeaders.PRAGMA, "no-cache");
        response.setContentType("image/jpeg");
        String text = kaptcha.createText();
        try (ServletOutputStream out = response.getOutputStream()) {
            request.getSession().setAttribute(KAPTCHA_SESSION_KEY, text);
            request.getSession().setAttribute(KAPTCHA_SESSION_DATE, Instant.now());
            ImageIO.write(kaptcha.createImage(text), "jpg", out);
            return text;
        } catch (IOException e) {
            throw new KaptchaException(e);
        }
    }

    @Override
    public boolean validate(String code) {
        return validate(code, 900);
    }

    @Override
    public boolean validate(String code, long second) {
        if (!StringUtils.isEmpty(code)) {
            HttpSession httpSession = request.getSession(false);
            if (httpSession != null) {
                String sessionCode = (String) httpSession.getAttribute(KAPTCHA_SESSION_KEY);
                if (sessionCode.equalsIgnoreCase(code)) {
                    Instant instant = (Instant) httpSession.getAttribute(KAPTCHA_SESSION_DATE);
                    long duration = Duration.between(instant, Instant.now()).getSeconds();
                    if (duration < second) {
                        httpSession.removeAttribute(KAPTCHA_SESSION_KEY);
                        httpSession.removeAttribute(KAPTCHA_SESSION_DATE);
                        return true;
                    } else {
                        throw new KaptchaException();
                    }
                } else {
                    throw new KaptchaException();
                }
            } else {
                throw new KaptchaException();
            }
        } else {
            throw new KaptchaException();
        }
    }

}

